﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Composite;
using Microsoft.Practices.Composite.Presentation;
using T = System.Windows.Threading;
using TWC = Telerik.Windows.Controls;
using Dimok;
using Dimok.FilteredView;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace DataGridWithFilter {
	public partial class DataGrid : System.Windows.Controls.DataGrid, Dimok.DataContext.IDataContextChangedHandler<DataGridWithFilter.DataGrid> {
    #region Fields
    readonly string _filterHeaderStyle = "FilterHeaderStyle";
    readonly string IconRowHeaderStyle = "IconRowHeaderStyle";
    readonly string ColumnsMenuItemStyle = "ColumnsMenuItemStyle";
    DataGridBoundColumn[] DataBoundColumns { get { return Columns.OfType<DataGridBoundColumn>().ToArray(); } }
    DataGridBoundColumn[] DataBoundColumnsVisible { get { return DataBoundColumns.Where(c => c.Visibility == Visibility.Visible).ToArray(); } }
    System.Threading.SynchronizationContext CurrentContext { get { return System.Threading.SynchronizationContext.Current; } }
    FrameworkElement headerPanel = null;
    TWC.RadContextMenu columnsMenu = null;
    TWC.RadContextMenu filterMenu = null;
    Style _rowMenuStyle = null;
    public Style RowMenuStyle {
      get { return _rowMenuStyle; }
      set { _rowMenuStyle = value; }
    }
    bool _profileLoading = false;
		public TextBlock RowsCountTextBlock;
		TWC.RadComboBox _profilesRadComboBox;

		public TWC.RadComboBox ProfilesRadComboBox {
			get { return _profilesRadComboBox; }
			set {
				if( _profilesRadComboBox == value )return;
				_profilesRadComboBox = value;
				ProfilesRadComboBox.ItemsSource = ProfileDataContext.ProfilesCollection;
			}
		}
		public int RowsCount { get { return (int)ItemsSource.GetPropertyOrNull("Count"); } }
		public bool IsCtrl = false;
		#endregion

    #region Properties
    public IFilteredView FilteredSource { get { return ItemsSource as IFilteredView; } }
    public string[] VisibleColumns() {
        return DataBoundColumnsVisible.OrderBy(c => c.DisplayIndex).Select(c => c.Binding.Path.Path).ToArray();
    }
		public ProfileModel ProfileDataContext {
			get {
				var dc = DataContext as ProfileModel;
				if (dc == null) {
					System.Windows.Browser.HtmlPage.Window.Alert("DataContext is of type " + typeof(ProfileModel).Name);
					return new ProfileModel();
				}
				return dc;
			}
		}
		public string ReportName { get { return ProfilesRadComboBox.Text; } }
    #endregion

    #region ctor



		public DelegateCommand<MouseButtonEventArgs> ShowColumnMenuCommand {
			get { return (DelegateCommand<MouseButtonEventArgs>)GetValue(ShowColumnMenuCommandProperty); }
			set { SetValue(ShowColumnMenuCommandProperty, value); }
		}

		// Using a DependencyProperty as the backing store for ShowColumnMenuCommand.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty ShowColumnMenuCommandProperty =
				DependencyProperty.Register("ShowColumnMenuCommand", typeof(DelegateCommand<MouseButtonEventArgs>), typeof(DataGrid),null);



		public DataGrid Me {
			get { return (DataGrid)GetValue(MeProperty); }
			set { SetValue(MeProperty, value); }
		}

		// Using a DependencyProperty as the backing store for Me.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty MeProperty =
				DependencyProperty.Register("Me", typeof(DataGrid), typeof(DataGrid), null);



		public DataGrid()
			: base() {
			Me = this;
			ShowColumnMenuCommand = new DelegateCommand<MouseButtonEventArgs>(e => {
				var button = e.OriginalSource as FrameworkElement;
				e.Handled = true;
				CurrentContext.Post(a => ShowColumnsMenu(button), null);
			}, bb => true);
			if (DataVisualization.DesignerProperties.GetIsInDesignMode()) return;
			Dimok.DataContext.DataContextChangedHelper<DataGrid>.Bind(this);
			AutoGenerateColumns = false;
			Loaded += new RoutedEventHandler(DataGrid_Loaded);
			
			KeyDown += (sender, e) => { if (e.Key == Key.Ctrl) IsCtrl = true; };
			KeyUp += (sender, e) => { if (e.Key == Key.Ctrl) IsCtrl = false; };
			this.SetBinding(InternalItemsSourceProperty, new Binding("ItemsSource") { Source = this });
			this.SetBinding(InternalHeadersVisibilityProperty, new Binding("HeadersVisibility") { Source = this });

			var xaml = Dimok.ResourceHelper.GetXamlObject("Themes/generic.xaml", this.AssembleyName());
			var rd = xaml as ResourceDictionary;
			this.Resources.MergedDictionaries.Add(rd);
			if (/*ShowFilter && */ColumnHeaderStyle == null)
				ColumnHeaderStyle = Resources[_filterHeaderStyle] as Style;
			//DataGridStyleWithHeader
			//if (!Application.Current.Resources.Contains("DataGridCaptionStyle"))
			//  Application.Current.Resources.Add("DataGridCaptionStyle", new Themes.DataGridCaption().Resources["DataGridCaptionStyle"]);
			//this.Style = new Themes.DataGridStyle().Resources["DataGridStyleWithHeader"] as Style;
			this.Style = Resources["DataGridStyleWithHeader"] as Style;
		}


    #endregion

    #region Overrides
    protected override void OnColumnDisplayIndexChanged(DataGridColumnEventArgs e) {
      base.OnColumnDisplayIndexChanged(e);
			FilteredSource.OnColumnsChanged();
			//if (FilteredSource != null) FilteredSource.Columns = VisibleColumns;
    }
    protected override void OnColumnReordered(DataGridColumnEventArgs e) {
      base.OnColumnReordered(e);
    }
    public override void OnApplyTemplate() {
      base.OnApplyTemplate();
    }
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e) {
      base.OnAutoGeneratingColumn(e);
      var dc = ItemsSource as IFilteredView;
      var et = dc.EntityType;
      var propName = ((DataGridBoundColumn)e.Column).Binding.Path.Path;
      var propType = et.GetProperty(propName).PropertyType;
    }
    #endregion

    #region Event Handlers



		public DataGridHeadersVisibility InternalHeadersVisibility {
			get { return (DataGridHeadersVisibility)GetValue(InternalHeadersVisibilityProperty); }
			set { SetValue(InternalHeadersVisibilityProperty, value); }
		}

		// Using a DependencyProperty as the backing store for InternalHeadersVisibility.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty InternalHeadersVisibilityProperty =
				DependencyProperty.Register("InternalHeadersVisibility", typeof(DataGridHeadersVisibility), typeof(DataGrid), new PropertyMetadata(
					(d, e) => {
						var dg = d as DataGridWithFilter.DataGrid;
						if (((uint)dg.HeadersVisibility & 2) == 2 && dg.RowHeaderStyle == null)
							dg.RowHeaderStyle = dg.Resources[dg.IconRowHeaderStyle] as Style;
					}));


		public static readonly DependencyProperty InternalItemsSourceProperty =
				DependencyProperty.Register("InternalItemsSource", typeof(IEnumerable), typeof(DataGrid), new PropertyMetadata(
					(d, e) => {
						var dg = d as DataGridWithFilter.DataGrid;
						var source = e.NewValue as IFilteredView;
						if (source != null) {
							source.GridProfileLoaded += new EventHandler<GridProfileLoadedEventArgs>(dg.source_GridProfileLoaded);
							source.Refreshed += new EventHandler<RefreshEventArgs>(dg.source_Refreshed);
							source.FilterDescriptions.CollectionChanged += new NotifyCollectionChangedEventHandler(dg.FilterDescriptions_CollectionChanged);
							source.Columns = dg.VisibleColumns;
							source.ReportName = () => dg.ReportName;
							source.Refreshing += new EventHandler<RefreshEventArgs>((s, evt) => {
								if (dg.dt != null) dg.dt.Stop();
							});
							dg.ProfileDataContext.GetFilteredSource = () => dg.FilteredSource;
							dg.ProfileDataContext.GetProfile(dg.FilteredSource,"");
						}
					}
					));


    void DataGrid_Loaded(object sender, RoutedEventArgs e) {}

		void FilterDescriptions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			var filterDescriptions = (sender as FilterDescriptionCollection).Select(fd=>fd.Member);
			if (e.Action == NotifyCollectionChangedAction.Reset) {
				var tbs1 = from fb in filterBoxes.Where(tb => tb.Text != "")
									 select new { TextBox = fb, Filter = GetFilterPropertyName(fb) };
				var tbs = from filter in filterBoxes.Where(tb => tb.Text != "").Select(tb => new { TextBox = tb, Filter = GetFilterPropertyName(tb) })
									join fd in filterDescriptions on filter.Filter equals fd into fdGroup
									from fdg in fdGroup.DefaultIfEmpty()
									where fdg == null
									select filter;
				tbs.ToList().ForEach(tbf => tbf.TextBox.Text = "");
			}
		}
    void source_Refreshed(object sender, RefreshEventArgs e) {
      if (_profileLoading) {
        _profileLoading = false;
        SelectedIndex = -1;
      }
			if (RowsCountTextBlock != null) RowsCountTextBlock.Text = RowsCount.ToString("n0");
    }
		Dimok.Shared.ReportProfile ProfileCurrent;
    void source_GridProfileLoaded(object sender, GridProfileLoadedEventArgs e) {
			_profileLoading = true;
			ProfileCurrent = e.ReportProfile;

			//ProfileDataContext.SelectedProfile = ProfilesCollection.Where(p => p.Value == ProfileCurrent.ReportName).First();
			
			var source = ItemsSource as IFilteredView;
			var scv = ItemsSource as ICollectionView;
			var elementType = (source).EntityType;
      var defaultColumns = new Func<IEnumerable<string>>(() => 
        ProfileCurrent.GetDefaultColumns(elementType) ?? elementType.GetProperties().Take(10).Select(p => p.Name)
      );
      var profileColumns = e.ReportProfile.Columns != null && e.ReportProfile.Columns.Length > 0 ? e.ReportProfile.Columns : defaultColumns();

			#region Sort ====================
			source.CanSort = false;
			scv.SortDescriptions.Clear();
			foreach (var s in e.ReportProfile.Sorts)
				scv.SortDescriptions.Add(new SortDescription(s.Key, (System.ComponentModel.ListSortDirection)(int)s.Value));
			source.CanSort = true;
			#endregion ======================

			#region Columns =================
			foreach (var p in profileColumns.Distinct().Join(elementType.GetProperties(), pc => pc, p => p.Name, (pc, p) => p))
        AddColumn(elementType, p, e.ReportProfile.Filters, true, e.ReportProfile.MetaTables);
      foreach (var p in elementType.GetProperties().Where(p=>!profileColumns.Contains(p.Name)))
        AddColumn(elementType, p, e.ReportProfile.Filters, false, e.ReportProfile.MetaTables);
			#endregion ======================

			#region Filter ==================
			source.CanFilter = false;
			if (ProfileDataContext.ShowFilter.HasValue && ProfileDataContext.ShowFilter.Value) {
				if (e.ReportProfile.Filters != null) {
					source.FilterDescriptions.ClearFilters();
					foreach (var f in e.ReportProfile.Filters) {
						source.FilterDescriptions.Add(f.Key, f.Value);
						//var textBox = filterBoxes.Where(tb => tb.DataContext + "" == GetColumnByFilterPropertyName(f.Key).Header + "").SingleOrDefault();
						//if (textBox != null) textBox.Text = f.Value;
					}
				}
      }
			source.CanFilter = true;
			#endregion ======================

			scv.Refresh();
    }
		TextBox GetTextBoxByFilterPropertyName(string propertyName) {
			var header = GetColumnByFilterPropertyName(propertyName).Header + "";
			var textBox = filterBoxes.Where(tb => tb.DataContext + "" == header).SingleOrDefault();
			if (textBox == null) throw new Exception("No text box is assigned to [" + header + "] columnn.");
			return textBox;
		}
		#region AddCoulumn
    public class ColumnGeneratedEventArgs:EventArgs{
      public DataGridBoundColumn Column { get; set; }
    }
    public event EventHandler<ColumnGeneratedEventArgs> ColumnGenerated;
    void OnColumnGenerated(DataGridBoundColumn column) {
      if (ColumnGenerated != null) ColumnGenerated(this, new ColumnGeneratedEventArgs() { Column = column });
    }
    void AddColumn(Type entityType, PropertyInfo p, Dictionary<string, string> filters,bool visible,Dimok.Shared.MetaTablesDictionary metaData) {
			var col = Columns.OfType<DataGridTextColumn>().SingleOrDefault(c => c.Binding.Path.Path == p.Name);
			if (col == null) {
				col = new DataGridTextColumn();
				col.Header = p.Name.MakeHeader();//.Replace(" ", Environment.NewLine); ;
				col.Binding = new System.Windows.Data.Binding(p.Name);
				string formatString = "";
				if (metaData.ContainsKey(entityType.Name)) {
					var metaFields = metaData[entityType.Name];
					if (metaFields != null && metaFields.ContainsKey(p.Name))
						formatString = metaFields[p.Name].FormatString;
				}
				if (formatString == "" && p.PropertyType.GetBaseType() == typeof(DateTime))
					formatString = "MM/dd/yy";
				if (formatString != "") {
					col.Binding.Converter = new Dimok.Converters.StringFormatter();
					col.Binding.ConverterParameter = formatString;
				}

				Columns.Add(col);
			}
			col.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
			var filter = filters != null && filters.ContainsKey(p.Name) ? filters[p.Name] : "";
      OnColumnGenerated(col);
    }
    #endregion

    internal T.DispatcherTimer dt = null;
    void textBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
      if (dt == null) {
        dt = new T.DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) }; 
        dt.Tick += new EventHandler((s, evt) => {
          ShowColumnsMenu(headerPanel);
          dt.Stop();
        });
      }
      headerPanel = sender as FrameworkElement;
      dt.Start();
    }
    void AddFilterDescription(TextBox tb) {
			try {
				var fd = FilteredSource.FilterDescriptions.Add(GetFilterPropertyName(tb));
				var bindingExpression = tb.GetBindingExpression(TextBox.TextProperty);
				if (bindingExpression != null) return;
				tb.SetBinding(TextBox.TextProperty, new Binding("Value") { Source = fd, Mode = BindingMode.TwoWay });
			} catch (Exception exc) { ShowExceptionBox(exc); }
    }
		string GetFilterPropertyName(TextBox tb) { return GetFilterPropertyName(tb.DataContext + ""); }
		string GetFilterPropertyName(string columnHeader) {return GetColumnByHeader(columnHeader).Binding.Path.Path;		}
		DataGridBoundColumn GetColumnByHeader(string columnHeader) {
			var column = Columns.Where(c => c.Header + "" == columnHeader).SingleOrDefault();
			if (column == null) throw new Exception("Column " + columnHeader + " not found.");
			return column as DataGridBoundColumn;
		}
		DataGridBoundColumn GetColumnByFilterPropertyName(string filterPropertyName) {
			var column = Columns.Cast<DataGridBoundColumn>().Where(c => c.Binding.Path.Path == filterPropertyName).SingleOrDefault();
			if (column == null) throw new Exception("Column  with filter [" + filterPropertyName + "] property not found.");
			return column;
		}
		Type GetFilterPropertyType(string columnHeader) {
			return FilteredSource.EntityType.GetProperty(GetFilterPropertyName(columnHeader)).PropertyType;
		}
		#endregion

		#region Helpers
		void ShowExceptionBox(Exception exc) {
			MessageBox.Show(exc.Message + Environment.NewLine + exc.StackTrace);
		}
		public void RemoveProfile(string profileName) {

		}
		public void ClearFilters() {
			FilteredSource.FilterDescriptions.Clear();
		}
		public void ResetPageLayout() {
			try {
				var dc = DataContext as ProfileModel;
				if (dc != null) dc.OnResetPageLayout();
			} catch (Exception exc) {
				throw exc;
			}
		}
		#endregion

		#region Dependecy Properties




		public static string GetRowsCountFE(DependencyObject obj) {
			return (string)obj.GetValue(RowsCountFEProperty);
		}

		public static void SetRowsCountFE(DependencyObject obj, string value) {
			obj.SetValue(RowsCountFEProperty, value);
		}

		// Using a DependencyProperty as the backing store for RowsCountFE.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty RowsCountFEProperty =
				DependencyProperty.RegisterAttached("RowsCountFE", typeof(string), typeof(System.Windows.Controls.DataGrid), new PropertyMetadata(
(DependencyObject d, DependencyPropertyChangedEventArgs e) => {
	System.Diagnostics.Debugger.Break();
}
));



		#region IsPageLayoutMaster


		public bool IsPageLayoutMaster {
			get { return (bool)GetValue(IsPageLayoutMasterProperty); }
			set { SetValue(IsPageLayoutMasterProperty, value); }
		}

		// Using a DependencyProperty as the backing store for IsPageLayoutMaster.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty IsPageLayoutMasterProperty =
				DependencyProperty.Register("IsPageLayoutMaster", typeof(bool), typeof(DataGrid), new PropertyMetadata(IsPageLayoutMasterPropertyChanged));
		public static void IsPageLayoutMasterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			if (!(bool)e.NewValue) return;
			//var dg = d as DataGrid;
			//(dg.DataContext as ProfileModel).LayoutDataGrid = dg;
		}


		#endregion


    #region Aggregates
		#region Retired
		[TypeConverter(typeof(Dimok.Converters.StringToListTypeConverter))]
		/*public*/ List<string> AverageColumns {
			get { return (List<string>)GetValue(AverageColumnsProperty); }
			set { SetValue(AverageColumnsProperty, value); }
		}
		/*public*/ static readonly DependencyProperty AverageColumnsProperty =
				DependencyProperty.Register("AverageColumns", typeof(List<string>), typeof(DataGrid), new PropertyMetadata(null));

		[TypeConverter(typeof(Dimok.Converters.StringToListTypeConverter))]
		/*public*/ List<string> TotalColumns {
			get { return (List<string>)GetValue(TotalColumnsProperty); }
			set { SetValue(TotalColumnsProperty, value); }
		}
		/*public*/ static readonly DependencyProperty TotalColumnsProperty =
				DependencyProperty.Register("TotalColumns", typeof(List<string>), typeof(DataGrid), new PropertyMetadata(null));
		#endregion

		public string Average {
      get { return (string)GetValue(AverageProperty); }
      set { SetValue(AverageProperty, value); }
    }
    public static readonly DependencyProperty AverageProperty =
        DependencyProperty.Register("Average", typeof(string), typeof(FrameworkElement), new PropertyMetadata(AveragePropertyChanged));
    public static void AveragePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
      var tb = d as TextBlock;
      var dg = d.GetParent<DataGrid>();
      if (dg == null) return;
			var dc = dg.ProfileDataContext as ProfileModel;
			var propertyName = dg.GetFilterPropertyName(e.NewValue + "");
			//if (dg.AverageColumns == null || dg.AverageColumns.Join(dg.DataBoundColumnsVisible, a => a, c => c.Binding.Path.Path, (a, c) => a).Count() == 0)
			if (!dc.Averages.ContainsKey(propertyName))
        tb.Text = "";
      else
        tb.SetBinding(TextBlock.TextProperty, new Binding("Value") {
          Source = dc.Averages[propertyName],
          Converter = new Dimok.Converters.DefaultFormatConverter()
        });
    }



    public string Total {
      get { return (string)GetValue(TotalProperty); }
      set { SetValue(TotalProperty, value); }
    }
    public static readonly DependencyProperty TotalProperty =
        DependencyProperty.Register("Total", typeof(string), typeof(FrameworkElement), new PropertyMetadata(TotalPropertyChanged));
    static void TotalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
      var tb = d as TextBlock;
      var dg = d.GetParent<DataGrid>();
      if (dg == null) return;
			var dc = dg.ProfileDataContext as ProfileModel;
			var propertyName = dg.GetFilterPropertyName(e.NewValue + "");
			//if (dg.TotalColumns == null || dg.TotalColumns.Join(dg.DataBoundColumnsVisible, a => a, c => c.Binding.Path.Path, (a, c) => a).Count() == 0)
			if (!dc.Totals.ContainsKey(propertyName))
				tb.Text = "";
      else
        if (dc.Totals.ContainsKey(propertyName)) {
          tb.SetBinding(TextBlock.TextProperty, new Binding("Value") {
						Source = dc.Totals[propertyName],
						Converter = new Dimok.Converters.DefaultFormatConverter()
          });
        }
    }


    #endregion

		#region Filter
    List<TextBox> filterBoxes = new List<TextBox>();

    public static string GetFilter(DependencyObject obj) {
      return (string)obj.GetValue(FilterProperty);
    }
    public static void SetFilter(DependencyObject obj, string value) {
      obj.SetValue(FilterProperty, value);
    }
    public static readonly DependencyProperty FilterProperty =
        DependencyProperty.RegisterAttached("Filter", typeof(string), typeof(DataGrid),
        new PropertyMetadata("", FilterPropertyCallback));
		public static void FilterPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			try {
				var tb = d as TextBox;
				var dg = d.GetParent<DataGrid>();
				if (dg == null) return;
				if (!dg.filterBoxes.Contains(tb)) dg.filterBoxes.Add(tb);

				bool canFilter = dg.FilteredSource.CanFilter;
				dg.FilteredSource.CanFilter = false;
				dg.AddFilterDescription(tb);
				dg.FilteredSource.CanFilter = canFilter;
					
				tb.KeyDown += new KeyEventHandler(dg.FilterBox_KeyDown);
				tb.KeyUp += new KeyEventHandler(dg.FilterBox_KeyUp);
				//tb.GotFocus += new RoutedEventHandler((sender, e1) => ((TextBox)sender).SelectAll());
				//var filterDescription = dg.FilteredSource.FilterDescriptions.Where(fd => fd.Member == dg.GetFilterPropertyName(tb)).SingleOrDefault();
				//if (filterDescription != null) tb.Text = filterDescription.Value;
				//var image = VisualTreeHelper.GetChild(VisualTreeHelper.GetParent(tb), 1) as Image;
				//SetFilterTextBox(image, tb);
				//if (image.Visibility == Visibility.Visible)
				//  image.MouseLeftButtonDown += new MouseButtonEventHandler(dg.FilterImage_MouseLeftButtonDown);
				var textBlock = ((StackPanel)((StackPanel)tb.Parent).Parent).Children.OfType<TextBlock>().First();
				textBlock.MouseLeftButtonDown += new MouseButtonEventHandler(dg.textBlock_MouseLeftButtonDown);
			} catch (Exception exc) {
				throw exc;
			}
		}
		bool keyShift = false;
		internal void FilterBox_KeyUp(object sender, KeyEventArgs e) {
			if (e.Key == Key.Shift) keyShift = false;
		}
		internal void FilterBox_KeyDown(object sender, KeyEventArgs e) {
			if (e.Key == Key.Shift) keyShift = true;
			if (e.Key == Key.Enter || e.Key == Key.Tab) {
				e.Handled = true;
				var tb = sender as TextBox;
				if (e.Key == Key.Tab) {
					var t = filterBoxes[Math.Max(0, filterBoxes.IndexOf(tb) + (keyShift ? -1 : 1) % filterBoxes.Count)];
					t.Focus();
					t.SelectAll();
				} else {
					tb.Focus();
					tb.SelectAll();
				}
				//this.ScrollIntoView(0, Columns[20]);
				//AddFilterDescription(tb);
			}
		}
private void FilterImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
      var image = sender as Image;
      e.Handled = true;
      CurrentContext.Post((a) => ShowColumnsMenu(sender as FrameworkElement), null);
      //ShowFiltersMenu(image);
    }
    #endregion


    #region Show Filter,Totals,Averages
		/*
		static void SavePageLayout(DependencyObject d,DependencyPropertyChangedEventArgs e){
			var dg = (DataGrid)d;
			if (!dg._profileLoading) {
				dg.SavePageLayout();
			}
		}
		//Filter
    public bool? ShowFilter {
      get { return (bool?)GetValue(ShowFilterProperty); }
      set { SetValue(ShowFilterProperty, value); }
    }
    public static readonly DependencyProperty ShowFilterProperty =
        DependencyProperty.Register("ShowFilter", typeof(bool?), typeof(DataGrid),new PropertyMetadata(null,SavePageLayout));
		//Totals
		public bool? ShowTotals {
			get { return (bool?)GetValue(ShowTotalsProperty); }
			set { SetValue(ShowTotalsProperty, value); }
		}
		public static readonly DependencyProperty ShowTotalsProperty =
				DependencyProperty.Register("ShowTotals", typeof(bool?), typeof(DataGrid), new PropertyMetadata(null, SavePageLayout));
		//Averages
		public bool? ShowAverages {
			get { return (bool?)GetValue(ShowAveragesProperty); }
			set { SetValue(ShowAveragesProperty, value); }
		}
		public static readonly DependencyProperty ShowAveragesProperty =
				DependencyProperty.Register("ShowAverages", typeof(bool?), typeof(DataGrid), new PropertyMetadata(null,SavePageLayout));
		*/
		#endregion

		void SavePageLayout() {
			ProfileDataContext.SavePageLayoutAsync(FilteredSource, 
				new Dimok.Shared.ReportProfile(), 
				new CancelEventArgs());
		}

    #region FilterTextBox
    static TextBox GetFilterTextBox(DependencyObject obj) {
      var tb = obj.GetValue(FilterTextBoxProperty) as TextBox;
      if (tb == null) throw new Exception("No TextBox is attached to " + obj.ToString());
      return tb;
    }
    static void SetFilterTextBox(DependencyObject obj, TextBox value) {
      obj.SetValue(FilterTextBoxProperty, value);
    }
    static readonly DependencyProperty FilterTextBoxProperty =
    DependencyProperty.Register("FilterTextBox", typeof(TextBox), typeof(Image), null);
    #endregion


    #endregion

		#region Excel
		public void ShowExcel() {
			FilteredSource.OnExcel();
		}
		#endregion

		#region IDataContextChangedHandler<DataGrid> Members !!!

		public void DataContextChanged(DataGrid sender, DependencyPropertyChangedEventArgs e) {
			var pdc = e.OldValue as ProfileModel;
			if (pdc != null) {
				pdc.ProfileSaved -= ProfileSavedHandler;
			}
			pdc = e.NewValue as ProfileModel;
			if (pdc == null) {
				MessageBox.Show(GetType().Name + " grid in " + Application.Current.RootVisual.GetType().FullName + " has DataContext other then " + typeof(ProfileModel).FullName);
				return;
			}
			pdc.ProfileSaved += ProfileSavedHandler;

			if (IsPageLayoutMaster)
				(e.NewValue as ProfileModel).GetFilteredSource = () => sender.FilteredSource;
		}

		void ProfileSavedHandler(object sender, ProfileModelBase.ProfileSavedEventArgs e) {
			if( e.ProfileName!="")
				MessageBox.Show("Profile " + e.ProfileName + " saved.");
		}

		#endregion
	}

	#region ThemesDataContext !!!
	public class ThemesDataContext {
		public static ImageSource RowHeaderIcon {
			get {
				return
					ResourceHelper.GetBitmap("Images/bullet_wrench.png", Dimok.Extentions.AssembleyName<ThemesDataContext>());
			}
		}
		public ThemesDataContext() {

		}
		static ThemesDataContext() { }
	}
	#endregion

}

#region ResourceManager !!!
internal static class ResourceManager {
	private static Dictionary<string, ResourceDictionary> _resourceDictionaryCache = new Dictionary<string, ResourceDictionary>();
	/// <summary>    
	/// GetResourceDictionary    
	/// </summary>    
	public static ResourceDictionary GetResourceDictionary(string name) {
		var resourceName = name;
		if (string.IsNullOrEmpty(resourceName)) { resourceName = "generic.xaml"; }
		ResourceDictionary retVal = null;
		if (_resourceDictionaryCache.TryGetValue(resourceName, out retVal)) {
			return retVal;
		}
		System.Reflection.Assembly assembly = typeof(ResourceManager).Assembly;
		string baseName = string.Format("{0}.g", assembly.FullName.Split(new char[] { ',' })[0]);
		string fullName = string.Format("{0}.resources", baseName);
		foreach (string s in assembly.GetManifestResourceNames()) {
			if (s == fullName) {
				System.Resources.ResourceManager manager = new System.Resources.ResourceManager(baseName, assembly);
				using (System.IO.Stream stream = manager.GetStream(resourceName)) {
					using (System.IO.StreamReader reader = new System.IO.StreamReader(stream)) {
						retVal = System.Windows.Markup.XamlReader.Load(reader.ReadToEnd()) as ResourceDictionary;
						if (retVal != null) {
							_resourceDictionaryCache.Add(resourceName, retVal); return retVal;
						}
					}
				}
				break;
			}
		} return null;
	}
}
#endregion
